表单验证
1. 概述
在现代 Web 应用中,表单是用户与应用交互的主要方式之一。为了确保用户输入的数据是有效的,表单验证是不可或缺的一部分。Angular 提供了强大的表单验证功能,支持模板驱动表单和响应式表单两种方式。本教程将详细介绍如何在 Angular 中进行表单验证。
2. 模板驱动表单验证
2.1 基本概念
模板驱动表单(Template-driven Forms)是一种基于模板的表单验证方式,适合简单的表单场景。在这种方式下,表单的验证逻辑主要写在模板文件中。
2.2 示例代码
<!-- app.component.html -->
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm)">
<label for="name">Name:</label>
<input type="text" id="name" name="name" ngModel required>
<div *ngIf="myForm.controls['name']?.invalid && (myForm.controls['name']?.dirty || myForm.controls['name']?.touched)">
<div *ngIf="myForm.controls['name']?.errors?.['required']">
Name is required.
</div>
</div>
<button type="submit" [disabled]="myForm.invalid">Submit</button>
</form>
2.3 解释
ngModel:用于双向数据绑定,同时也会将输入框注册到表单中。required:HTML5 的必填验证属性。#myForm="ngForm":将表单绑定到一个模板引用变量myForm。(ngSubmit)="onSubmit(myForm)":表单提交时调用onSubmit方法,并传递表单对象。[disabled]="myForm.invalid":禁用提交按钮,直到表单有效。
2.4 实践练习
- 创建一个新的 Angular 项目。
- 在
app.component.html中添加上述表单代码。 - 在
app.component.ts中实现onSubmit方法。
3. 响应式表单验证
3.1 基本概念
响应式表单(Reactive Forms)是一种基于模型的表单验证方式,适合复杂的表单场景。在这种方式下,表单的验证逻辑主要写在组件类中。
3.2 示例代码
// app.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
myForm: FormGroup;
constructor(private fb: FormBuilder) {
this.myForm = this.fb.group({
name: ['', Validators.required]
});
}
onSubmit() {
if (this.myForm.valid) {
console.log(this.myForm.value);
}
}
}
<!-- app.component.html -->
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<label for="name">Name:</label>
<input type="text" id="name" formControlName="name">
<div *ngIf="myForm.get('name')?.invalid && (myForm.get('name')?.dirty || myForm.get('name')?.touched)">
<div *ngIf="myForm.get('name')?.errors?.['required']">
Name is required.
</div>
</div>
<button type="submit" [disabled]="myForm.invalid">Submit</button>
</form>
3.3 解释
FormBuilder:用于简化表单组的创建。FormGroup:表示表单的组,包含多个表单控件。Validators.required:必填验证器。formControlName:将输入框绑定到表单控件。[formGroup]="myForm":将表单绑定到组件类中的表单组。
3.4 实践练习
- 创建一个新的 Angular 项目。
- 在
app.component.ts中添加上述代码。 - 在
app.component.html中添加表单模板代码。
4. 自定义验证器
4.1 基本概念
有时内置的验证器无法满足需求,这时可以创建自定义验证器。自定义验证器可以是一个函数,也可以是一个指令。
4.2 示例代码
// custom-validators.ts
import { AbstractControl, ValidationErrors } from '@angular/forms';
export function forbiddenNameValidator(nameRe: RegExp): (control: AbstractControl) => ValidationErrors | null {
return (control: AbstractControl): ValidationErrors | null => {
const forbidden = nameRe.test(control.value);
return forbidden ? { forbiddenName: { value: control.value } } : null;
};
}
// app.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { forbiddenNameValidator } from './custom-validators';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
myForm: FormGroup;
constructor(private fb: FormBuilder) {
this.myForm = this.fb.group({
name: ['', [Validators.required, forbiddenNameValidator(/admin/i)]]
});
}
onSubmit() {
if (this.myForm.valid) {
console.log(this.myForm.value);
}
}
}
4.3 解释
forbiddenNameValidator:自定义验证器函数,检查输入值是否包含禁止的名称。Validators.required:必填验证器。forbiddenNameValidator(/admin/i):使用自定义验证器,检查输入值是否包含 "admin"。
4.4 实践练习
- 创建一个新的 Angular 项目。
- 在项目中创建
custom-validators.ts文件,并添加自定义验证器代码。 - 在
app.component.ts中使用自定义验证器。
5. 动态表单
5.1 基本概念
动态表单允许根据数据动态生成表单控件。这在需要根据用户输入或外部数据动态调整表单结构时非常有用。
5.2 示例代码
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
myForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.myForm = this.fb.group({
emails: this.fb.array([
this.fb.control('', [Validators.required, Validators.email])
])
});
}
get emails() {
return this.myForm.get('emails') as FormArray;
}
addEmail() {
this.emails.push(this.fb.control('', [Validators.required, Validators.email]));
}
onSubmit() {
if (this.myForm.valid) {
console.log(this.myForm.value);
}
}
}
<!-- app.component.html -->
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<div formArrayName="emails">
<div *ngFor="let email of emails.controls; let i = index" [formGroupName]="i">
<label for="email{{i}}">Email {{i + 1}}:</label>
<input type="email" id="email{{i}}" formControlName="email">
<div *ngIf="email.invalid && (email.dirty || email.touched)">
<div *ngIf="email.errors?.['required']">
Email is required.
</div>
<div *ngIf="email.errors?.['email']">
Email is invalid.
</div>
</div>
</div>
</div>
<button type="button" (click)="addEmail()">Add Email</button>
<button type="submit" [disabled]="myForm.invalid">Submit</button>
</form>
5.3 解释
FormArray:用于动态添加表单控件。emails.push(this.fb.control('', [Validators.required, Validators.email])):动态添加新的电子邮件输入框。formArrayName="emails":将表单数组绑定到模板。[formGroupName]="i":将表单控件绑定到数组中的特定索引。
5.4 实践练习
- 创建一个新的 Angular 项目。
- 在
app.component.ts中添加动态表单代码。 - 在
app.component.html中添加表单模板代码。
6. 总结
表单验证是 Angular 应用中非常重要的一部分。通过模板驱动表单和响应式表单,我们可以轻松地实现各种复杂的验证逻辑。自定义验证器和动态表单进一步扩展了表单验证的能力,使得我们可以应对各种复杂的业务需求。
通过本教程的学习,你应该能够掌握 Angular 中的表单验证技术,并能够在实际项目中应用这些知识。